package common.cacher
{
    import flash.utils.Dictionary;
    import flash.utils.getTimer;

    import kernel.core.Core;
    import kernel.events.ServerEvent;

    /**
     *  http数据缓存池
     *  自动管理
     * @author 黄孟柱
     *
     */
    public class HttpCacher
    {
        protected var _head:uint;
        protected var _classRef:Class;
        protected var _idFied:Array;
        protected var _queue:Array;
        protected var _map:Object;

        private var _mapcallback:Object;

        private var _max:int;
        private var _size:int;
        private var _life:int;
        protected var _idMap:Dictionary;

        /**
         * 构造函数
         * @param head 取数据的协议头
         * @param classRef 数据对象的类型
         * @param idField 数据的id字段名
         * @param life 数据寿命，单位为毫秒,默认20分钟
         * @param maxcache 最大缓存数量
         * @param usize 当缓存数量超过最大缓存数时一次性移除旧数据的数量
         *
         */
        public function HttpCacher(head:uint , classRef:Class , idField:Array , life:int = 1200000 , maxcache:int = 500 , usize:int = 50)
        {
            _life = life;
            _max = maxcache;
            _size = usize;
            _head = head;
            _classRef = classRef;
            _idFied = idField;
            _queue = [];
            _idMap = new Dictionary ();
            _map = new Object ();
            _mapcallback = new Object ();
        }


        /**
         *  通过id获取对应的数据对象
         * @param id
         * @param callback 回调函数，格式为 callback（object ）
         *
         */
        public function getCache(id:* , callback:Function):void
        {
            var strId:String = id.toString ();
            var data:* = getObj (strId);
            if (data != null)
            {
                callback.call (null , data);
            }
            else
            {
                addCallback (strId , callback);
                sendMessage (id);
            }
        }

        protected function getObj(strId:String):*
        {

            var data:Array = _map[strId] as Array;
            if (data)
            {
                if (getTimer () - int (data[1]) < _life)
                {
                    return data[0];
                }
                else
                {
                    deletetillId (strId);
                }
            }
            return null;
        }

        protected function addCallback(id:String , callback:Function):void
        {
            var callbacklist:Array = _mapcallback[id] as Array;
            if (callbacklist)
            {
                callbacklist.push (callback);
            }
            else
            {
                callbacklist = [callback];
                _mapcallback[id] = callbacklist;
            }
        }

        protected function getId(data:*):*
        {
            var tem:* = data;
            var len:int = _idFied.length;
            for (var i:int = 0 ; i < len ; i++)
            {
                tem = tem[_idFied[i]];
            }
            return tem;
        }

        protected function sendMessage(id:*):void
        {
            throw new Error ("必须实现 sendMessage（）方法");
        }

        protected function ongetData(event:ServerEvent):void
        {
            if (event.berror)
            {
                callbackNULL (event.ident.toString ());
                return;
            }
            deleteOlded ();

            var data:* = event.createMessage (_classRef);
            decodeData (data);

        }

        protected function callbackNULL(id:String):void
        {
            var callbacklist:Array = _mapcallback[id] as Array;
            if (callbacklist)
            {

                var len:int = callbacklist.length;
                for (var i:int = 0 ; i < len ; ++i)
                {
                    var callback:Function = callbacklist[i];
                    if (callback != null)
                    {
                        callback.call (null , null);
                    }
                }
                callbacklist.length = 0;
                delete _mapcallback[id];
            }
        }

        protected function decodeData(data:*):void
        {
            var id:String = getId (data).toString ();
            _map[id] = [data , getTimer ()];
            _queue.push (id);
            var callbacklist:Array = _mapcallback[id] as Array;
            if (callbacklist)
            {

                var len:int = callbacklist.length;
                for (var i:int = 0 ; i < len ; ++i)
                {
                    var callback:Function = callbacklist[i];
                    if (callback != null)
                    {
                        callback.call (null , data);
                    }
                }
                callbacklist.length = 0;
                delete _mapcallback[id];
            }
        }

        /**
         * 删除最旧的usize个数据
         *
         */
        protected function deleteOlded():void
        {
            if (_queue.length >= _max)
            {
                var queuedelete:Array = _queue.splice (0 , _size);
                var len:int = queuedelete.length;
                for (var i:int = 0 ; i < len ; ++i)
                {
                    var id:* = queuedelete[i];
                    delete _map[id];
                }
            }
        }

        /**
         * 依次删除直到遇到指定的id
         * @param id
         *
         */
        protected function deletetillId(id:String):void
        {
            var len:int = _queue.length;
            var index:int = 0;
            for (index = 0 ; index < len ; ++index)
            {
                var tid:* = _queue[index];
                delete _map[tid];
                if (tid === id)
                {
                    ++index;
                    break;
                }
            }
            _queue.splice (0 , index);
        }

        public function remove(id:*):void
        {
            var len:int = _queue.length;
            var strId:String = id.toString ();
            for (var index:int = 0 ; index < len ; ++index)
            {
                var tid:* = _queue[index];
                if (tid === strId)
                {
                    delete _map[tid];
                    _queue.splice (index , index);
                    break;
                }
            }

        }
    }
}
